home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 1
/
Deutsche Edition 1.iso
/
amok
/
amok_lha
/
amok70.lha
/
PL0
/
txt
/
PL0Scanner.mod
< prev
next >
Wrap
Text File
|
1993-08-15
|
6KB
|
270 lines
(*************************************************************************
:Program. PL0Scanner.mod
:Contents. Text-Scanner for PL0-Complier
:Author. N. With, ported to Oberon by hartmut Goebel
:Language. Oberon
:Translator. Amiga Oberon
:Imports. TextWindows (hartmut Goebel)
*************************************************************************)
MODULE PL0Scanner;
IMPORT
fs: FileSystem, NoGuru,
sys: SYSTEM,
str: Strings,
tw: TextWindows;
CONST
(* Symbol *)
null* = 0; odd* = 1; times* = 2; div* = 3; plus* = 4;
minus* = 5; eql* = 6; neq* = 7; lss* = 8; leq* = 9;
gtr* = 10; geq* = 11; comma* = 12; rparen* = 13;
then* = 14; do* = 15; lparen* = 16; becomes* = 17;
number* = 18; ident* = 19; semicolon* = 20; end* = 21;
call* = 22; if* = 23; while* = 24; begin* = 25;
read* = 26; write* = 27; const* = 28; var* = 29;
procedure* = 30; period* = 31; eof* = 32;
VAR
sym*: INTEGER; (* last Symbol read *)
id*: INTEGER; (* character Buffer Index *)
num*: INTEGER; (* last number read *)
source*: fs.File;
TYPE
keyTable = ARRAY 20 OF
RECORD sym: INTEGER; ind: INTEGER; END;
CONST
maxCard = MAX(INTEGER);
bufLen = 1000;
VAR
keyTab: ARRAY 20 OF
RECORD sym: INTEGER; ind: INTEGER; END;
VAR
ch: ARRAY 1 OF CHAR; (* last character read *)
id0, id1: INTEGER; (* indices to identifier Buffer *)
win: tw.TxtWinPtr;
K: INTEGER; (* no of key words *)
buf*: ARRAY bufLen OF CHAR;
(* charkter buffer:
identifiers are stored with leading length count *)
PROCEDURE Mark*(n: INTEGER);
BEGIN
tw.Inversid(win);
tw.WriteInt(win,n,3);
tw.Normal(win);
END Mark;
PROCEDURE GetCh;
BEGIN
IF fs.ReadChar(source,ch[0]) THEN
IF ch >=" " THEN
tw.WriteString(win,ch);
ELSE
tw.WriteLn(win);
END;
ELSE
ch[0] := 0X;
END;
END GetCh;
PROCEDURE Diff*(u,v: INTEGER): INTEGER;
(* difference between identifier at buf[u] and buf[v] *)
VAR
w: INTEGER;
BEGIN
w := ORD(buf[u]);
LOOP
IF w = 0 THEN RETURN 0;
ELSIF buf[u] # buf[v] THEN
RETURN ORD(buf[u])-ORD(buf[v]);
ELSE
DEC(w); INC(u); INC(v);
END;
END;
END Diff;
PROCEDURE KeepId*;
BEGIN id := id1 END KeepId;
PROCEDURE Identifier;
VAR
k, l, m, d: INTEGER;
BEGIN
id1 := id;
IF id1 < bufLen THEN INC(id1) END;
REPEAT
IF id1 < bufLen THEN
buf[id1] := ch[0]; INC(id1); END;
GetCh;
UNTIL (ch[0]<"0") OR (ch[0]>"9") & (CAP(ch[0])<"A") OR (CAP(ch[0])>"Z");
buf[id] := CHR(id1-id); (* Length *)
k := 0;
(*l := K; REPEAT
m := (k+l) DIV 2; d := Diff(id,keyTab[m].ind);
IF d <= 0 THEN l := m-1; END;
IF d >= 0 THEN k := m+1; END;
UNTIL k>l;
IF k > l+1 THEN sym := keyTab[m].sym;
ELSE sym := ident; END;
*)
sym := ident;
REPEAT
IF Diff(id,keyTab[k].ind) = 0 THEN
sym := keyTab[k].sym;
RETURN;
END;
INC(k);
UNTIL k=K;
END Identifier;
PROCEDURE Number;
VAR
i, j, k, d: INTEGER;
dig: ARRAY 32 OF CHAR;
BEGIN
i := 0; sym := number;
REPEAT
dig[i] := ch[0]; INC(i); GetCh;
UNTIL (ch[0]<"0") OR (ch[0]>"9") & (CAP(ch[0])<"A") OR (CAP(ch[0])>"Z");
j := 0; k := 0;
REPEAT
d := ORD(dig[j])-ORD("0");
IF (d < 10) & ((maxCard-d) DIV 10 >= k) THEN
k := 10*k+d;
ELSE
Mark(30); k := 0;
END;
INC(j);
UNTIL j=i;
num := k;
END Number;
PROCEDURE GetSym*;
VAR
xch: ARRAY 1 OF CHAR;
PROCEDURE Comment;
BEGIN
GetCh;
REPEAT
WHILE ch[0] # "*" DO GetCh; END;
GetCh;
UNTIL ch[0] = ")";
GetCh;
END Comment;
BEGIN
LOOP (* ignore control characters *)
IF ch[0] <= " " THEN
IF ch[0] = 0X THEN EXIT END;
GetCh;
ELSIF ch[0] >= 7FX THEN GetCh;
ELSE EXIT;
END;
END;
CASE ch[0] OF (* " " <= ch[0] <= 7FC *)
0X : sym := eof; |
" ": sym := eof; ch[0] := 0X |
"!": sym := write; GetCh |
'"': sym := null; GetCh |
"#": sym := neq; GetCh |
"$": sym := null; GetCh |
"%": sym := null; GetCh |
"&": sym := null; GetCh |
"'": sym := null; GetCh |
"(": GetCh;
IF ch[0] = "*" THEN Comment; GetSym
ELSE sym := lparen;
END |
")": sym := rparen; GetCh |
"*": sym := times; GetCh |
"+": sym := plus; GetCh |
",": sym := comma; GetCh |
"-": sym := minus; GetCh |
".": sym := period; GetCh |
"/": sym := div; GetCh |
"0".."9": Number |
":": GetCh;
IF ch[0] = "=" THEN GetCh; sym := becomes;
ELSE sym := null;
END |
";": sym := semicolon; GetCh |
"=": sym := eql; GetCh |
"<": GetCh;
IF ch[0] = "=" THEN GetCh; sym := leq;
ELSE sym := lss;
END |
">": GetCh;
IF ch[0] = "=" THEN GetCh; sym := geq;
ELSE sym := gtr;
END |
"?": sym := read; GetCh |
"@": sym := null; GetCh |
"A".."Z", "a".."z": Identifier |
"[".."`": sym := null; GetCh |
"{".."~": sym := null; GetCh |
ELSE
END;
END GetSym;
PROCEDURE InitScanner*;
BEGIN
ch[0] := " ";
IF id0 = 0 THEN id0 := id;
ELSE id := id0; tw.ClrHome(win); tw.Normal(win);
END;
END InitScanner;
PROCEDURE EnterKW(sym: INTEGER; name: ARRAY OF CHAR);
VAR
l, L: INTEGER;
BEGIN
keyTab[K].sym := sym;
keyTab[K].ind := id;
l := 0; L := str.Length(name);
buf[id] := CHR(L+1);
INC(id);
WHILE l<=L DO
buf[id] := name[l];
INC(id); INC(l);
END;
INC(K);
END EnterKW;
BEGIN
K := 0; id := 0; id0 := 0;
EnterKW(do,"DO");
EnterKW(if,"IF");
EnterKW(end,"END");
EnterKW(odd,"ODD");
EnterKW(var,"VAR");
EnterKW(call,"CALL");
EnterKW(then,"THEN");
EnterKW(begin,"BEGIN");
EnterKW(const,"CONST");
EnterKW(while,"WHILE");
EnterKW(procedure,"PROCEDURE");
win := tw.OpenTextWin("PROGRAMM",0,0,640,100);
IF (win=NIL) THEN HALT(20); END;
CLOSE
IF win # NIL THEN tw.CloseTextWin(win); END;
END PL0Scanner.